<template>
<div
        class="shape_transform"
        @mousedown="mousedown($event)"
        @mousemove="mousemove($event)"
        @mouseup="mouseup()"
        @mousewheel="mousewheel($event)"
        @mouseleave="mouseleave()"
    >
        <!--所有li模块-->
        <ul class="ul" :style="ulStyle">
            <li class="li" v-for="(item, index) in list" :key="index" :style="item.style">
                <div class="title">CSS</div>
                <div class="info">亦或演示</div>
                <div class="info">2021-09-24</div>
            </li>
        </ul>
        <!--左下角按钮-->
        <div class="btn_list">
            <div class="btn" @click="changeShape('table')">表格</div>
            <div class="btn" @click="changeShape('sphere')">球体</div>
            <div class="btn" @click="changeShape('helix')">螺旋</div>
            <div class="btn" @click="changeShape('grid')">层叠</div>
        </div>
    </div>
</template>
<script lang="ts">
import { defineComponent } from "vue";
import MouseTransform from "@/utils/mouse_transform";

interface ShapeStyle {
    table: Style[];
    sphere: Style[];
    helix: Style[];
    grid: Style[];
}
interface Style {
    transform: string;
}
export default defineComponent({
    data() {
        return {
            length: 5 * 5 * 5,
            list: [],
            mt: null as MouseTransform,
            // 变换样式
            transform: {
                rotateX: 0,
                rotateY: 0,
                translateZ: -2000,
            },
            lastX: 0, // 鼠标最后位置
            lastY: 0,
            reduceX: 0, // 鼠标移动距离
            reduceY: 0,
            moveTime: 0, // 鼠标移动时间戳
            decayTimer: 0, // 衰减定时器
            isDown: false, // 是否按下鼠标
        };
    },
    computed: {
        // 容器样式
        ulStyle() {
            return {
                transform:
                    "translateZ(" +
                    this.transform.translateZ +
                    "px) rotateX(" +
                    this.transform.rotateX +
                    "deg) rotateY(" +
                    this.transform.rotateY +
                    "deg)",
            };
        },
        //表格样式
        tableStyle(): Style[] {
            var tableStyle = [];
            var n = Math.ceil(this.length / 18) + 2;
            var midY = n / 2 - 0.5;
            var midX = 18 / 2 - 0.5;
            var disX = 170;
            var disY = 210;
            var arr = [
                { x: 0, y: 0 },
                { x: 17, y: 0 },
                { x: 0, y: 1 },
                { x: 1, y: 1 },
                { x: 12, y: 1 },
                { x: 13, y: 1 },
                { x: 14, y: 1 },
                { x: 15, y: 1 },
                { x: 16, y: 1 },
                { x: 17, y: 1 },
                { x: 0, y: 2 },
                { x: 1, y: 2 },
                { x: 12, y: 2 },
                { x: 13, y: 2 },
                { x: 14, y: 2 },
                { x: 15, y: 2 },
                { x: 16, y: 2 },
                { x: 17, y: 2 },
            ];
            for (let i = 0; i < this.length; i++) {
                var x, y;
                if (i < 18) {
                    x = arr[i].x;
                    y = arr[i].y;
                } else {
                    x = i % 18;
                    y = Math.floor(i / 18) + 2;
                }
                tableStyle.push({
                    transform:
                        "translate3D(" +
                        (x - midX) * disX +
                        "px, " +
                        (y - midY) * disY +
                        "px, 0px)",
                });
            }
            return tableStyle;
        },
        // 球样式
        sphereStyle(): Style[] {
            var sphereStyle = [];
            var arr = [1, 3, 7, 9, 11, 14, 21, 16, 12, 10, 9, 7, 4, 1],
                arrLength = arr.length,
                xDeg = 180 / (arrLength - 1);
            for (let i = 0; i < this.length; i++) {
                //求出当前 i 处于arr的第几层 第几个
                var numC = 0,
                    numG = 0;
                var arrSum = 0;
                for (var j = 0; j < arrLength; j++) {
                    arrSum += arr[j];
                    if (arrSum > i) {
                        numC = j;
                        numG = arr[j] - (arrSum - i);
                        break;
                    }
                }
                var yDeg = 360 / arr[numC];
                sphereStyle.push({
                    transform:
                        "rotateY(" +
                        (numG + 1.3) * yDeg +
                        "deg) rotateX(" +
                        (90 - numC * xDeg) +
                        "deg) translateZ(800px)",
                });
            }
            return sphereStyle;
        },
        // 螺旋样式
        helixStyle(): Style[] {
            var helixStyle = [];
            var h = 3.7, //环数
                tY = 7, //每个li上下位移相差
                num = Math.round(this.length / h), //每环个数
                deg = 360 / num, //每个li Y旋转相差
                mid = this.length / 2 - 0.5; //找准中间点
            for (let i = 0; i < this.length; i++) {
                helixStyle.push({
                    transform:
                        "rotateY(" +
                        i * deg +
                        "deg) translateY(" +
                        (i - mid) * tY +
                        "px) translateZ(800px)",
                });
            }
            return helixStyle;
        },
        // 网格样式
        gridStyle(): Style[] {
            var gridStyle = [];
            var disX = 350; //每个li 水平（x）方向的间距
            var disY = 350; //每个li 垂直（y）方向的间距
            var disZ = 800; //每个li 纵深（z）方向的间距
            for (let i = 0; i < this.length; i++) {
                var oLi = this.list[i];
                var x = (oLi.x - 2) * disX,
                    y = (oLi.y - 2) * disY,
                    z = (oLi.z - 2) * disZ;
                gridStyle.push({
                    transform: "translate3D(" + x + "px," + y + "px," + z + "px)",
                });
            }
            return gridStyle;
        },
    },
    methods: {
        //页面初始化
        init() {
            // 初始化鼠标变换工具
            this.mt = new MouseTransform(this.transform);
            // 面板数量
            for (let i = 0; i < this.length; i++) {
                //初始的随机位置
                let tX = Math.random() * 6000 - 3000;
                let tY = Math.random() * 6000 - 3000;
                let tZ = Math.random() * 6000 - 3000;
                this.list.push({
                    // 层叠布局中的坐标
                    x: i % 5,
                    y: Math.floor((i % 25) / 5),
                    z: Math.floor(i / 25),
                    // 位置样式
                    style: {
                        transform: "translate3D(" + tX + "px," + tY + "px," + tZ + "px)",
                    },
                });
            }
            setTimeout(() => {
                this.changeShape("grid");
            }, 200);
        },
        mousedown(event: MouseEvent) {
            this.mt.mousedown(event);
        },
        mousemove(event: MouseEvent) {
            this.mt.mousemove(event);
        },
        mouseup() {
            this.mt.mouseup();
        },
        mousewheel(event: WheelEvent) {
            this.mt.mousewheel(event);
        },
        mouseleave() {
            this.mt.mouseleave();
        },
        // 更换形状
        changeShape(shape: keyof ShapeStyle) {
            let shapeStyle: ShapeStyle = {
                table: this.tableStyle,
                sphere: this.sphereStyle,
                helix: this.helixStyle,
                grid: this.gridStyle,
            };
            let styleList = shapeStyle[shape];
            for (var i = 0; i < this.length; i++) {
                this.list[i].style = styleList[i];
            }
        },
    },
    created() {
        this.init();
    },
});
</script>
<style scoped lang="scss" src="./shape.scss"></style>